package no.uio.ifi.cop.util;

// this stuff did not work, as thread is already dead
// if we were able to prove something, this approach only
// works for non-solvable theorems, not very clever :-)

/// import java.lang.management.ManagementFactory;
/// import java.lang.management.ThreadMXBean;

import no.uio.ifi.cop.common.Log;

/**
 * TimedRunner lets you run a Stoppable for a certain
 * amount of time before it is stopped.
 *
 *
 * @version 1.0
 * @author  bjarneh@ifi.uio.no
 */


public class TimedRunner implements Runnable{

    Stoppable job;

    long pause;
    long stop;

    long userTime;


    public TimedRunner( Stoppable job, long milliseconds ){
        this(job, milliseconds, 50); // default pause..
    }


    public TimedRunner( Stoppable job, long milliseconds, long pause ){
        this.job   = job;
        this.stop  = milliseconds;
        this.pause = pause;
    }

    public void run(){

        long max = System.currentTimeMillis() + stop;
        long now;

        // not 100% accurate timing method
        long iterations = 1;

        Thread forkedJob = new Thread(job);
        // Thread.currentThread() has MAX_PRIORITY I think..
        forkedJob.setPriority(Thread.MIN_PRIORITY);
        forkedJob.start();

        do{
            try{
                Thread.sleep(pause);
            }catch(InterruptedException ie){
                Log.warning("%s", ie);
            }

            now = System.currentTimeMillis();
            iterations++;

        }while( job.isRunning() && now < max );

        // store something similar to time used by prover Thread
        userTime = iterations * pause;

        while( job.isRunning() ){

            job.stop();

            Log.info("job is still running (%s)", job);

            try{
                Thread.sleep(pause);
            }catch(InterruptedException ie){
                Log.warning("%s",ie);
            }
        }


        while( forkedJob.isAlive() ){
            try{
                forkedJob.join(0);
                Thread.sleep(pause);
            }catch(InterruptedException ie){
                Log.warning("%s",ie);
            }
        }
    }

    public long getUserTimeMillis(){
        return userTime;
    }

    public long getUserTimeSeconds(){
        return userTime/1000L;
    }

    public String getFormattetUserTime(){
        double total = (double) getUserTimeMillis()/1000;
        return String.format("%.3fs", total);
    }
}
